#ifndef __NDIM_UTIL_HH__
#define __NDIM_UTIL_HH__

#include <vector>
#include <iostream>
#include <iterator>
using namespace std;

class NDimRangeTraverseCB 
{
public:
  virtual ~NDimRangeTraverseCB();
  virtual void do_it(const vector<size_t>& coor) = 0;
};

class NDimRange
{
public:
  vector<pair<size_t, size_t> > region_shape;
  vector<size_t> shape;
  size_t recurse_level;
  vector<size_t> curr_coor;

  NDimRange(const vector<size_t>& region_shape,
	     const vector<size_t>& shape);
  NDimRange(const vector<pair<size_t, size_t> >& region_shape,
	     const vector<size_t>& shape); 

  void traverse(NDimRangeTraverseCB* cb); 

private:
  void traverse_dimension(NDimRangeTraverseCB* cb, size_t i_dim);
};

size_t get_direct_index(const vector<size_t>& shape,
			const vector<size_t>& coor);

template <class T>
inline
void print_coor(ostream& out, const vector<T>& coor)
{
  out << "(";
  copy(coor.begin(), coor.end(), ostream_iterator<T>(out, ","));
  out << ")";
}

#endif
